package org.ehe.finance.voucher.controller;

import cn.dev33.satoken.annotation.SaCheckPermission;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.validation.Valid;
import jakarta.validation.constraints.NotNull;
import lombok.RequiredArgsConstructor;
import org.ehe.common.core.BaseController;
import org.ehe.common.core.domain.R;
import org.ehe.common.log.annotation.Log;
import org.ehe.common.log.enums.BusinessType;
import org.ehe.common.mybatis.core.page.PageQuery;
import org.ehe.common.mybatis.core.page.TableDataInfo;
import org.ehe.common.satoken.utils.LoginHelper;
import org.ehe.finance.voucher.domain.bo.*;
import org.ehe.finance.voucher.domain.vo.ErpFinanceVoucherVo;
import org.ehe.finance.voucher.mapper.ErpFinanceVoucherMapper.VoucherStatusCount;
import org.ehe.finance.voucher.service.ErpFinanceVoucherService;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import java.time.LocalDate;
import java.util.List;
/**
 * 记账凭证管理控制器
 * @author :zhangnn
 * @className :ErpFinanceVoucherController
 * @description: TODO
 * @date 2025-08-25 09:39:10
 */
@RestController
@RequestMapping("/finance/voucher")
@RequiredArgsConstructor
@Validated
public class ErpFinanceVoucherController extends BaseController{
    private final ErpFinanceVoucherService voucherService;

    /**
     * 分页查询记账凭证
     * @param bo
     * @param pageQuery
     * @return
     */
    @GetMapping("/page")
    @SaCheckPermission("finance:voucher:list")
    public TableDataInfo<ErpFinanceVoucherVo> page(@Valid VoucherQueryBo bo, PageQuery pageQuery) {
        return voucherService.pageVouchers(bo, pageQuery);
    }

    /**
     * 获取记账凭证详情
     * @param id
     * @return
     */
    @GetMapping("/{id}")
    @SaCheckPermission("finance:voucher:query")
    public R<ErpFinanceVoucherVo> getById(@PathVariable @NotNull Long id) {
        ErpFinanceVoucherVo result = voucherService.getVoucherById(id);
        return R.ok(result);
    }

    /**
     * 创建记账凭证
     * @param createBo
     * @return
     */
    @Log(title = "创建记账凭证", linkType = "finance", businessType = BusinessType.INSERT, idField = "id", nameField = "period")
    @PostMapping
    @SaCheckPermission("finance:voucher:add")
    public R<Long> create(@Valid @RequestBody VoucherCreateBo createBo) {
        Long id = voucherService.createVoucher(createBo);
        return R.ok("创建成功", id);
    }

    /**
     * 更新记账凭证
     * @param updateBo
     * @return
     */
    @Log(title = "更新记账凭证", linkType = "finance", businessType = BusinessType.UPDATE, idField = "id", nameField = "period")
    @PostMapping("/edit")
    @SaCheckPermission("finance:voucher:edit")
    public R<Void> update(@Valid @RequestBody VoucherUpdateBo updateBo) {
        voucherService.updateVoucher(updateBo);
        return R.ok("更新成功");
    }

    /**
     * 删除记账凭证
     * @param id
     * @return
     */
    @Log(title = "删除记账凭证", linkType = "finance", businessType = BusinessType.DELETE, idField = "id", nameField = "id")
    @PostMapping("/{id}")
    @SaCheckPermission("finance:voucher:remove")
    public R<Void> delete(@PathVariable @NotNull Long id) {
        voucherService.deleteVoucher(id);
        return R.ok("删除成功");
    }

    /**
     * 批量删除记账凭证
     * @param ids
     * @return
     */
    @DeleteMapping("/batch")
    @SaCheckPermission("finance:voucher:remove")
    public R<Void> batchDelete(@RequestBody @NotNull List<Long> ids) {
        voucherService.batchDeleteVouchers(ids);
        return R.ok("删除成功");
    }

    /**
     * 审核凭证
     * @param id
     * @param reviewComment
     * @return
     */
    @Log(title = "审核记账凭证", linkType = "finance", businessType = BusinessType.UPDATE, idField = "id", nameField = "period")
    @PostMapping("/review/{id}")
    @SaCheckPermission("finance:voucher:review")
    public R<Void> review(@PathVariable @NotNull Long id,@RequestParam(required = false) String reviewComment) {
        voucherService.reviewVoucher(id, reviewComment);
        return R.ok("审核成功");
    }

    /**
     * 反审核凭证
     * @param id
     * @param reason
     * @return
     */
    @Log(title = "反审核记账凭证", linkType = "finance", businessType = BusinessType.UPDATE, idField = "id", nameField = "period")
    @PostMapping("/unreview/{id}")
    @SaCheckPermission("finance:voucher:review")
    public R<Void> unreview(@PathVariable @NotNull Long id,@RequestParam String reason) {
        voucherService.unreviewVoucher(id, reason);
        return R.ok("反审核成功");
    }

    /**
     * 记账
     * @param id
     * @return
     */
    @Log(title = "记账", linkType = "finance", businessType = BusinessType.UPDATE, idField = "id", nameField = "subjectName")
    @PostMapping("/post/{id}")
    @SaCheckPermission("finance:voucher:post")
    public R<Void> post(@PathVariable @NotNull Long id) {
        voucherService.postVoucher(id);
        return R.ok("记账成功");
    }

    /**
     * 反记账
     * @param id
     * @param reason
     * @return
     */
    @Log(title = "反记账", linkType = "finance", businessType = BusinessType.UPDATE, idField = "id", nameField = "reason")
    @PostMapping("/unpost/{id}")
    @SaCheckPermission("finance:voucher:post")
    public R<Void> unpost(@PathVariable @NotNull Long id,@RequestParam String reason) {
        voucherService.unpostVoucher(id, reason);
        return R.ok("反记账成功");
    }

    /**
     * 批量审核凭证
     * @param ids
     * @param reviewComment
     * @return
     */
    @Log(title = "批量审核凭证", linkType = "finance", businessType = BusinessType.UPDATE, idField = "id", nameField = "reviewComment")
    @PostMapping("/batch-review")
    @SaCheckPermission("finance:voucher:review")
    public R<Void> batchReview(@RequestBody @NotNull List<Long> ids, @RequestParam(required = false) String reviewComment) {
        voucherService.batchReviewVouchers(ids, reviewComment);
        return R.ok("批量审核成功");
    }

    /**
     * 批量记账
     * @param ids
     * @return
     */
    @Log(title = "批量记账", linkType = "finance", businessType = BusinessType.UPDATE, idField = "id", nameField = "id")
    @PostMapping("/batch-post")
    @SaCheckPermission("finance:voucher:post")
    public R<Void> batchPost(@RequestBody @NotNull List<Long> ids) {
        voucherService.batchPostVouchers(ids);
        return R.ok("批量记账成功");
    }

    /**
     * 结账
     * @param ids
     * @return
     */
    @Log(title = "结账", linkType = "finance", businessType = BusinessType.UPDATE, idField = "id", nameField = "id")
    @PostMapping("/close")
    @SaCheckPermission("finance:voucher:close")
    public R<Void> close(@RequestBody @NotNull List<Long> ids) {
        voucherService.closeVouchers(ids);
        return R.ok("结账成功");
    }


    /**
     * 反结账
     * @param ids
     * @param reason
     * @return
     */
    @PostMapping("/unclose")
    @SaCheckPermission("finance:voucher:close")
    public R<Void> unclose(@RequestBody @NotNull List<Long> ids, @RequestParam String reason) {
        voucherService.uncloseVouchers(ids, reason);
        return R.ok("反结账成功");
    }

    /**
     * 检查凭证号是否存在
     * @param voucherNo
     * @param excludeId
     * @return
     */
    @GetMapping("/check-voucher-no/{voucherNo}")
    @SaCheckPermission("finance:voucher:query")
    public R<Boolean> checkVoucherNo(@PathVariable String voucherNo,@RequestParam(required = false) Long excludeId) {
        boolean exists = voucherService.checkVoucherNoExists(voucherNo, excludeId);
        return R.ok(exists);
    }

    /**
     * 生成凭证号
     * @param voucherTypeId
     * @param period
     * @return
     */
    @GetMapping("/generate-no/{voucherTypeId}/{period}")
    @SaCheckPermission("finance:voucher:add")
    public R<String> generateVoucherNo(@PathVariable @NotNull Long voucherTypeId,@PathVariable String period) {
        String voucherNo = voucherService.generateVoucherNo(voucherTypeId, period);
        return R.ok(voucherNo);
    }

    /**
     * 获取下一个凭证号
     * @param voucherTypeId
     * @param voucherDate
     * @return
     */
    @GetMapping("/next-no/{voucherTypeId}")
    @SaCheckPermission("finance:voucher:add")
    public R<String> getNextVoucherNo(@PathVariable @NotNull Long voucherTypeId,@RequestParam LocalDate voucherDate) {
        String voucherNo = voucherService.getNextVoucherNo(voucherTypeId, voucherDate);
        return R.ok(voucherNo);
    }

    /**
     * 根据期间获取凭证列表
     * @param period
     * @return
     */
    @GetMapping("/period/{period}")
    @SaCheckPermission("finance:voucher:list")
    public R<List<ErpFinanceVoucherVo>> getVouchersByPeriod(@PathVariable String period) {
        List<ErpFinanceVoucherVo> result = voucherService.getVouchersByPeriod(period);
        return R.ok(result);
    }

    /**
     * 获取期间内凭证状态统计
     * @param period
     * @return
     */
    @GetMapping("/status-count/{period}")
    @SaCheckPermission("finance:voucher:list")
    public R<List<VoucherStatusCount>> getVoucherStatusCount(@PathVariable String period) {
        List<VoucherStatusCount> result = voucherService.getVoucherStatusCount(period);
        return R.ok(result);
    }

    /**
     * 根据来源单据查询凭证
     * @param sourceId
     * @param sourceNo
     * @return
     */
    @GetMapping("/source")
    @SaCheckPermission("finance:voucher:list")
    public R<List<ErpFinanceVoucherVo>> getVouchersBySource(@RequestParam(required = false) Long sourceId,
                                                            @RequestParam(required = false) String sourceNo) {
        List<ErpFinanceVoucherVo> result = voucherService.getVouchersBySource(sourceId, sourceNo);
        return R.ok(result);
    }

    /**
     * 复制凭证
     * @param id
     * @param newVoucherDate
     * @return
     */
    @PostMapping("/copy/{id}")
    @SaCheckPermission("finance:voucher:add")
    public R<Long> copyVoucher(@PathVariable @NotNull Long id,@RequestParam LocalDate newVoucherDate) {
        Long newId = voucherService.copyVoucher(id, newVoucherDate);
        return R.ok("复制成功", newId);
    }

    /**
     * 获取用户待审核凭证数量
     * @param userId
     * @return
     */
    @GetMapping("/pending-review-count")
    @SaCheckPermission("finance:voucher:review")
    public R<Long> getPendingReviewCount(@RequestParam(required = false) Long userId) {
        if (userId == null) {
            userId = LoginHelper.getUserId();
        }
        Long count = voucherService.getPendingReviewCount(userId);
        return R.ok(count);
    }

    /**
     * 验证凭证借贷平衡
     * @param id
     * @return
     */
    @GetMapping("/validate-balance/{id}")
    @SaCheckPermission("finance:voucher:query")
    public R<Boolean> validateBalance(@PathVariable @NotNull Long id) {
        boolean balanced = voucherService.validateBalance(id);
        return R.ok(balanced);
    }

    /**
     * 更新凭证金额合计
     * @param id
     * @return
     */
    @PostMapping("/update-totals/{id}")
    @SaCheckPermission("finance:voucher:edit")
    public R<Void> updateVoucherTotals(@PathVariable @NotNull Long id) {
        voucherService.updateVoucherTotals(id);
        return R.ok("更新成功");
    }

    /**
     * 检查期间是否已结账
     * @param period
     * @return
     */
    @GetMapping("/period-closed/{period}")
    @SaCheckPermission("finance:voucher:query")
    public R<Boolean> isPeriodClosed(@PathVariable String period) {
        boolean closed = voucherService.isPeriodClosed(period);
        return R.ok(closed);
    }

    /**
     * 获取凭证打印数据
     * @param id
     * @return
     */
    @Operation(summary = "")
    @SaCheckPermission("finance:voucher:query")
    public R<ErpFinanceVoucherVo> getVoucherForPrint(@PathVariable @NotNull Long id) {
        ErpFinanceVoucherVo result = voucherService.getVoucherForPrint(id);
        return R.ok(result);
    }

    /**
     * 导出凭证
     * @param bo
     * @return
     */
    @PostMapping("/export")
    @SaCheckPermission("finance:voucher:export")
    public R<Void> export(@Valid @RequestBody VoucherQueryBo bo) {
        // TODO: 实现凭证导出功能
        return R.ok("导出功能待实现");
    }

    /**
     * 导入凭证
     * @return
     */
    @PostMapping("/import")
    @SaCheckPermission("finance:voucher:import")
    public R<Void> importVouchers() {
        // TODO: 实现凭证导入功能
        return R.ok("导入功能待实现");
    }
}
